home *** CD-ROM | disk | FTP | other *** search
/ Especial Multimedia / Especial Multimedia.iso / Multimed / Prg / DLLGIF.ZIP / GIFENCOD.C < prev    next >
C/C++ Source or Header  |  1993-08-02  |  15KB  |  551 lines

  1. /***************************************************************************
  2.  *
  3.  *  GIFENCOD.C       - GIF Image compression routines
  4.  *
  5.  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
  6.  *  David Rowley (mgardi@watdcsu.waterloo.edu)
  7.  * GIF Image compression - modified 'compress'
  8.  *
  9.  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  10.  *
  11.  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  12.  *              Jim McKie               (decvax!mcvax!jim)
  13.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  14.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  15.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  16.  *              Joe Orost               (decvax!vax135!petsd!joe)
  17.  *
  18.  *                                                   
  19.  *    Windows mud-ifications by John Walsh CompuServe ID 70612,1740
  20.  *    08 Aug '93
  21.  ***************************************************************************/
  22.  
  23. #include <windows.h>
  24. #include <process.h>
  25. #include <stdlib.h>
  26. #include <stdio.h> 
  27.  
  28. #include "gifdll.h"
  29.  
  30. static void __near    char_init(void);                  
  31. static void __near    cl_hash(register long hsize);  /* reset code table */
  32. static void __near    output(int code );
  33. static void __near    cl_block (void);               /* table clear for block compress */
  34. static void __near    writeerr(void);
  35. static void __near    char_out(int c );
  36. static void __near    flush_char(void);
  37. static void __near    Putword(int w);
  38. static void __near    compress(int init_bits);
  39. static int     __near  GIFNextPixel(void);
  40. static void ClearAll(void);
  41. BOOL FAR PASCAL _export    GIFEncode(const char* FName,LPSTR lpDIB);
  42.  
  43. static     const BYTE _huge*    lpBits;
  44. static     FILE*                file;                    
  45. static     int                    g_init_bits;
  46. static     int                 Width, Height;
  47. static     long                 CountDown;
  48. static     int                 Pass;
  49. static     int                 Interlace;
  50.  
  51. #define BITS    12
  52. #define HSIZE  5003                    /* 80% occupancy */
  53. static    int n_bits=0;                   /* number of bits/code */
  54. static    int maxbits = BITS;                /* user settable max # bits/code */
  55. static    int maxcode=0;                  /* maximum code, given n_bits */
  56. static    int maxmaxcode = (int)1 << 12;     /* should NEVER generate this code */
  57. #define MAXCODE(n_bits)        (((int) 1 << (n_bits)) - 1)
  58.  
  59. static    long htab [5003];
  60. static    unsigned short codetab [HSIZE];
  61. #define HashTabOf(i)       htab[i]
  62. #define CodeTabOf(i)    codetab[i]
  63. static    int hsize = HSIZE;              /* for dynamic table sizing */
  64. static    long fsize=0;
  65. #define tab_prefixof(i) CodeTabOf(i)
  66. #define tab_suffixof(i)        ((char *)(htab))[i]
  67. #define de_stack               ((char *)&tab_suffixof((int)1<<BITS))
  68. static    int free_ent = 0;               /* first unused entry */
  69. static    int exit_stat = 0;
  70. static    int clear_flg = 0;
  71. static    int offset=0;
  72. static    long int in_count = 1;          /* length of input */
  73. static    long int out_count = 0;         /* # of codes output (for debugging) */
  74. static    int ClearCode=0;
  75. static    int EOFCode=0;
  76. static    unsigned long cur_accum = 0;
  77. static    int  cur_bits = 0;
  78. static    int a_count=0;
  79. static    char accum[ 256 ];
  80. static    DWORD    line=0; 
  81.  
  82.  
  83. static    unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  84.                                   0x001F, 0x003F, 0x007F, 0x00FF,
  85.                                   0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  86.                                   0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  87.  // Width & Height are global
  88. int __near GIFNextPixel(void)
  89. {
  90.     BYTE r;
  91.  
  92.     if( CountDown == 0 )
  93.         return EOF;                              
  94.         
  95.     if(line==0)
  96.     {
  97.         line=Width;
  98.         lpBits=((const BYTE _huge*)lpBits)-(DWORD)Width;
  99.     }    
  100.             
  101.     CountDown--;
  102.  
  103.     r = lpBits[Width-line];
  104.     line--;
  105.     
  106.     return (int)r;
  107. }
  108.  
  109. /***************************************************************************
  110.     FUNCTION :BOOL FAR PASCAL _export GIFEncode(const char* FName,
  111.                                                     LPSTR lpDIB)
  112.     
  113.     Here is the function that does all the work for the user. give it a
  114.     path/filename with the GIF extension, and a valid pointer to
  115.     a packed memory DIB (BITMAPINFO w/RGBQUAD + BITS), and it will do the
  116.     rest. 
  117.     See the readme.txt for limitations
  118. ***************************************************************************/
  119.  
  120. BOOL FAR PASCAL _export GIFEncode(const char* FName,LPSTR lpDIB)
  121. {
  122.     int                 B;
  123.     int                 GWidth,RWidth, RHeight,GHeight;
  124.     int                 LeftOfs, TopOfs, BitsPerPixel;
  125.     int                 Resolution;
  126.     int                 ColorMapSize;
  127.     int                 InitCodeSize;
  128.     int                 i;
  129.     LPBITMAPINFO        lpBMI;
  130.                            
  131.     ClearAll();                           
  132.     lpBMI=(LPBITMAPINFO)lpDIB;
  133.     
  134.     GWidth=(int)lpBMI->bmiHeader.biWidth;
  135.     GHeight=(int)lpBMI->bmiHeader.biHeight;
  136.     BitsPerPixel=lpBMI->bmiHeader.biBitCount;
  137.         
  138.     Interlace =0;
  139.     
  140.     ColorMapSize = 1 << BitsPerPixel;
  141.     
  142.     
  143.     line=RWidth = Width = GWidth;
  144.     RHeight = Height = GHeight;
  145.     LeftOfs = TopOfs = 0;
  146.     
  147.     Resolution = BitsPerPixel;
  148.  
  149.     // Calculate number of bits we are expecting
  150.     
  151.     CountDown = (long)Width * (long)Height;
  152.     lpBits= (const BYTE _huge*)(((const BYTE _huge*)lpDIB) +
  153.                  (((DWORD)CountDown-(DWORD)line)+(DWORD)(ColorMapSize*sizeof(RGBQUAD)
  154.                      +(DWORD)sizeof(BITMAPINFOHEADER))));
  155.  
  156.      // Indicate which pass we are on (if interlace) NOT SUPPPORTED YET
  157.  
  158.     Pass = 0;
  159.  
  160.      // The initial code size
  161.      
  162.     if( BitsPerPixel <= 1 )
  163.         InitCodeSize = 2;
  164.     else
  165.         InitCodeSize = BitsPerPixel;
  166.  
  167.      // Open the GIF file for binary write
  168.      
  169.     file = fopen( FName, "wb" );
  170.  
  171.     if( file == (FILE *)0 ) 
  172.     {     
  173.         MessageBox(NULL, "error: could not open output file",
  174.                     "File Error", MB_ICONSTOP|MB_SYSTEMMODAL );
  175.         return FALSE;
  176.     }
  177.  
  178.     
  179.     // Write the Magic header
  180.     
  181.     fputc( 'G', file );
  182.     fputc( 'I', file );
  183.     fputc( 'F', file );
  184.     fputc( '8', file );
  185.     fputc( '9', file );
  186.     fputc( 'a', file );
  187.  
  188.      // Write out the screen width and height
  189.      
  190.     Putword( RWidth);
  191.     Putword( RHeight);
  192.  
  193.     
  194.     // Indicate that there is a global colour map
  195.      
  196.     B = 0x80;    /* Yes, there is a color map */
  197.     
  198.      // OR in the resolution
  199.      
  200.     B |= (Resolution - 1) << 4;//5?
  201.  
  202.     // OR in the Bits per Pixel
  203.      
  204.     B |= (BitsPerPixel - 1);
  205.  
  206.     // Write it out packed fields
  207.      
  208.     fputc( B, file );
  209.  
  210.     // Write out the Background colour
  211.  
  212.     fputc( 0, file );
  213.  
  214.     // Byte of 0's pixel aspect ratio
  215.      
  216.     fputc( 0, file );
  217.  
  218.     // Write out the Global Colour Map
  219.      
  220.     for( i=0; i<ColorMapSize; i++ ) 
  221.     {
  222.         fputc( lpBMI->bmiColors[i].rgbRed, file );
  223.         fputc( lpBMI->bmiColors[i].rgbGreen, file );
  224.         fputc( lpBMI->bmiColors[i].rgbBlue, file );
  225.     }
  226.  
  227.     // Write an Image separator
  228.      
  229.     fputc( ',', file );
  230.  
  231.     // Write the Image header
  232.  
  233.     Putword( LeftOfs);
  234.     Putword( TopOfs);
  235.     Putword( Width);
  236.     Putword( Height);
  237.  
  238.     // Write out whether or not the image is interlaced IT'S NOT
  239.      
  240.     if( Interlace )
  241.         fputc( 0x40, file );
  242.     else
  243.         fputc( 0x00, file );
  244.  
  245.     // Write out the initial code size
  246.      
  247.     fputc( InitCodeSize, file );
  248.  
  249.     // Go and actually compress the data
  250.      
  251.     compress( InitCodeSize+1);
  252.  
  253.     // Write out a Zero-length packet (to end the series)
  254.     
  255.     fputc( 0, file );
  256.  
  257.     // Write the GIF file terminator
  258.      
  259.     fputc( ';', file );
  260.  
  261.     // And close the file
  262.      
  263.     fclose( file );                       
  264.     return TRUE;
  265.     
  266. }
  267.  
  268. //  Write out a word to the GIF file
  269.  
  270. static void __near Putword(int w)
  271. {
  272.     fputc( (w & 0xff), file );
  273.     fputc( ((w / 256) & 0xff), file );
  274. }
  275.  
  276. /*************************************************************************
  277.  * Algorithm:  use open addressing double hashing (no chaining) on the 
  278.  * prefix code / next character combination.  We do a variant of Knuth's
  279.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  280.  * secondary probe.  Here, the modular division first probe is gives way
  281.  * to a faster exclusive-or manipulation.  Also do block compression with
  282.  * an adaptive reset, whereby the code table is cleared when the compression
  283.  * ratio decreases, but after the table fills.  The variable-length output
  284.  * codes are re-sized at this point, and a special CLEAR code is generated
  285.  * for the decompressor.  Late addition:  construct the table according to
  286.  * file size for noticeable speed improvement on small files.  Please direct
  287.  * questions about this implementation to ames!jaw.
  288. *************************************************************************/
  289. static void __near compress(int init_bits)
  290. {
  291.     register long fcode=0;
  292.     register int i = 0;
  293.     register int c=0;
  294.     register int ent=0;
  295.     register int disp=0;
  296.     register int hsize_reg=0;
  297.     register int hshift=0;
  298.  
  299.     // Set up the necessary values
  300.                                   
  301.     g_init_bits=init_bits;
  302.      
  303.     offset = 0;
  304.     out_count = 0;
  305.     clear_flg = 0;
  306.     in_count = 1;
  307.     maxcode = MAXCODE(n_bits = g_init_bits);
  308.  
  309.     ClearCode = (1 << (init_bits - 1));
  310.     EOFCode = ClearCode + 1;
  311.     free_ent = ClearCode + 2;
  312.  
  313.     char_init();
  314.     
  315.     ent = GIFNextPixel();
  316.  
  317.     hshift = 0;
  318.     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  319.         hshift++;
  320.     hshift = 8 - hshift;                /* set hash code range bound */
  321.  
  322.     hsize_reg = hsize;                   
  323.     cl_hash( (long) hsize_reg);         /* clear hash table */
  324.  
  325.     output( (int)ClearCode );
  326.     
  327.     while ( (c = GIFNextPixel()) != EOF ) 
  328.     {
  329.         in_count++;
  330.  
  331.         fcode = (long) (((long) c << maxbits) + ent);
  332.         i = (((int)c << hshift) ^ ent);    /* xor hashing */
  333.  
  334.         if ( HashTabOf (i) == fcode ) 
  335.         {
  336.             ent = CodeTabOf (i);
  337.             continue;
  338.         }
  339.         else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
  340.             goto nomatch;
  341.         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
  342.         if ( i == 0 )
  343.             disp = 1;
  344. probe:
  345.         if ( (i -= disp) < 0 )
  346.             i += hsize_reg;
  347.  
  348.         if ( HashTabOf (i) == fcode ) {
  349.             ent = CodeTabOf (i);
  350.             continue;
  351.         }
  352.         if ( (long)HashTabOf (i) > 0 ) 
  353.             goto probe;
  354. nomatch:
  355.         output ( (int) ent );
  356.         out_count++;
  357.         ent = c;
  358.         if ( (long)free_ent < (long)maxmaxcode ) 
  359.         {
  360.             CodeTabOf (i) = free_ent++; /* code -> hashtable */
  361.             HashTabOf (i) = fcode;
  362.         }
  363.         else
  364.         cl_block();
  365.     }
  366.     // Put out the final code.
  367.      
  368.     output( (int)ent );
  369.     out_count++;
  370.     output( (int) EOFCode );
  371.  
  372.     return;
  373. }
  374.  
  375. /**************************************************************************
  376.  * TAG( output )
  377.  *
  378.  * Output the given code.
  379.  * Inputs:
  380.  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  381.  *              that n_bits =< (long)wordsize - 1.
  382.  * Outputs:
  383.  *      Outputs code to the file.
  384.  * Assumptions:
  385.  *      Chars are 8 bits long.
  386.  * Algorithm:
  387.  *      Maintain a BITS character long buffer (so that 8 codes will
  388.  * fit in it exactly).  Use the VAX insv instruction to insert each
  389.  * code in turn.  When the buffer fills up empty it and start over.
  390. **************************************************************************/
  391.  
  392.  
  393. static void __near output(int code )
  394. {
  395.     cur_accum &= masks[ cur_bits ];
  396.  
  397.     if( cur_bits > 0 )
  398.         cur_accum |= ((long)code << cur_bits);
  399.     else
  400.         cur_accum = code;
  401.     
  402.     cur_bits += n_bits;
  403.  
  404.     while( cur_bits >= 8 )
  405.     {
  406.         char_out( (unsigned int)(cur_accum & 0xff) );
  407.         cur_accum >>= 8;
  408.         cur_bits -= 8;
  409.     }
  410.  
  411.     /*
  412.      * If the next entry is going to be too big for the code size,
  413.      * then increase it, if possible.
  414.      */
  415.        if ( free_ent > maxcode || clear_flg ) 
  416.        {
  417.         if( clear_flg ) 
  418.         {
  419.             maxcode = MAXCODE (n_bits = g_init_bits);
  420.             clear_flg = 0;
  421.         }
  422.         else 
  423.         {
  424.             n_bits++;
  425.             if ( n_bits == maxbits )
  426.                 maxcode = maxmaxcode;
  427.             else
  428.                 maxcode = MAXCODE(n_bits);
  429.         }
  430.     }
  431.     
  432.     if( code == EOFCode ) 
  433.     {
  434.         /*
  435.          * At EOF, write the rest of the buffer.
  436.          */
  437.         while( cur_bits > 0 ) 
  438.         {
  439.             char_out( (unsigned int)(cur_accum & 0xff) );
  440.             cur_accum >>= 8;
  441.             cur_bits -= 8;
  442.         }
  443.         flush_char();
  444.         fflush( file );
  445.  
  446.         if( ferror( file ) )
  447.                 writeerr();
  448.     }
  449. }
  450.     
  451. /*
  452.  * Clear out the hash table
  453.  */
  454.  
  455. static void __near cl_block (void)             /* table clear for block compress */
  456. {
  457.     cl_hash ( (long) hsize );
  458.     free_ent = ClearCode + 2;
  459.     clear_flg = 1;
  460.     output( (int)ClearCode );
  461. }
  462.  
  463. static void __near cl_hash(register long hsize)          /* reset code table */
  464. {
  465.     register long *htab_p = htab+hsize;
  466.  
  467.     register long i=0;
  468.     register long m1 = -1;
  469.  
  470.     i = hsize - 16;
  471.     do 
  472.     {                            /* might use Sys V memset(3) here */
  473.         *(htab_p-16) = m1;
  474.         *(htab_p-15) = m1;
  475.         *(htab_p-14) = m1;
  476.         *(htab_p-13) = m1;
  477.         *(htab_p-12) = m1;
  478.         *(htab_p-11) = m1;
  479.         *(htab_p-10) = m1;
  480.         *(htab_p-9) = m1;
  481.         *(htab_p-8) = m1;
  482.         *(htab_p-7) = m1;
  483.         *(htab_p-6) = m1;
  484.         *(htab_p-5) = m1;
  485.         *(htab_p-4) = m1;
  486.         *(htab_p-3) = m1;
  487.         *(htab_p-2) = m1;
  488.         *(htab_p-1) = m1;
  489.         htab_p -= 16;
  490.     } while ((i -= 16) >= 0);
  491.  
  492.     for ( i += 16; i > 0; i-- )
  493.         *--htab_p = m1;
  494. }
  495.  
  496.  
  497. static void __near writeerr(void)
  498. {
  499.     MessageBox(NULL,"Error writing to gif file",
  500.                 "GIF write error",MB_ICONSTOP|MB_SYSTEMMODAL);
  501.     return;
  502. }
  503.  
  504. /*
  505.  * Set up the 'byte output' routine
  506.  */
  507.  
  508. static void __near char_init(void)
  509. {
  510.     a_count = 0;
  511. }
  512. /*
  513.  * Add a character to the end of the current packet, and if it is 254
  514.  * characters, flush the packet to disk.
  515.  */
  516.  
  517. static void __near char_out(int c )
  518. {
  519.     accum[ a_count++ ] = c;
  520.     if( a_count >= 254 ) 
  521.         flush_char();
  522. }
  523.  
  524. /*
  525.  * Flush the packet to disk, and reset the accumulator
  526.  */
  527.  
  528. static void __near flush_char(void)
  529. {
  530.     if( a_count > 0 ) 
  531.     {
  532.         fputc( a_count, file );
  533.         fwrite( accum, 1, a_count, file );
  534.         a_count = 0;
  535.     }
  536. }    
  537.  
  538. /* The End */
  539. static void ClearAll(void)
  540. {                       
  541. //    maxbits = BITS;     /* user settable max # bits/code */
  542.     free_ent = 0;       /* first unused entry */
  543.     clear_flg = 0;
  544.     offset=0;
  545.     in_count = 1;       /* length of input */
  546.     out_count = 0;      /* # of codes output (for debugging) */
  547.     cur_accum = 0;
  548.     cur_bits = 0;
  549.     a_count=0;
  550.     line=0; 
  551. }